﻿using System;
using System.Collections.Generic;
using EpiNEXT.Foundation;
using EpiNEXT.Services.Collections;
using EpiNEXT.Services.Fields;

namespace EpiNEXT.Services
{
    public class FieldCollectionFactory
    {
        #region Properties
        public Project Project { get; private set; }
        public DataEntryInstrument Form { get; private set; }
        #endregion // Properties

        #region Constructors
        [Obsolete("Use of default constructor not allowed", true)]
        private FieldCollectionFactory() { }

        public FieldCollectionFactory(Project project, DataEntryInstrument form)
        {
            this.Project = project;
            this.Form = form;
        }
        #endregion // Constructors

        public FieldCollection GetFieldCollection()
        {
            FieldsDTO fieldsDTO = Form.FieldsDTO;

            FieldCollection fieldCollection = new FieldCollection();
            fieldCollection.Form = this.Form;

            foreach (IField field in fieldsDTO.GroupFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.RectangleFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.StaticImageFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.LabelFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.DataGridFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.TextBoxFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.DatePickerFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.DateBoxFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.NumberFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.CheckBoxFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.RelateButtonFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.ImageFields)
            {
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.YesNoFields)
            {
                YesNoField ynField = field as YesNoField;

                ynField.Form = Form;
                if (ynField.IncludeUnknown)
                {
                    ynField.ListSource = ynField.Form.Owner.CodeListYNU;
                }
                else
                {
                    ynField.ListSource = ynField.Form.Owner.CodeListYN;
                }

                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.ComboBoxFields)
            {
                ComboBoxField comboBoxField = field as ComboBoxField;
                foreach (CodeList codeList in Project.CodeLists)
                {
                    if (codeList.Name == comboBoxField.ListSourceName)
                    {
                        comboBoxField.ListSource = codeList;
                    }
                }
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.ListBoxFields)
            {
                ListBoxField listBoxField = field as ListBoxField;
                foreach (CodeList codeList in Project.CodeLists)
                {
                    if (codeList.Name == listBoxField.ListSourceName)
                    {
                        listBoxField.ListSource = codeList;
                    }
                }
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.RadioButtonListFields)
            {
                RadioButtonListField listField = field as RadioButtonListField;
                foreach (CodeList codeList in Project.CodeLists)
                {
                    if (codeList.Name == listField.ListSourceName)
                    {
                        listField.ListSource = codeList;
                    }
                }
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.CheckBoxListFields)
            {
                CheckBoxListField listField = field as CheckBoxListField;
                foreach (CodeList codeList in Project.CodeLists)
                {
                    if (codeList.Name == listField.ListSourceName)
                    {
                        listField.ListSource = codeList;
                    }
                }
                fieldCollection.Add(field);
            }

            foreach (IField field in fieldsDTO.CommandButtonFields)
            {
                fieldCollection.Add(field);
            }

            // Do these last because they rely on fieldCollection to have the source field already
            foreach (IField field in fieldsDTO.MirrorFields)
            {
                MirrorField mirrorField = field as MirrorField;
                foreach (IField iField in fieldCollection)
                {
                    if (iField.FieldId == mirrorField.FieldIdToMirror)
                    {
                        mirrorField.FieldToMirror = iField as Field;
                    }
                }
                fieldCollection.Add(field);
            }

            // assign pages and forms
            foreach (IField field in fieldCollection)
            {
                if (Form is Form)
                {
                    field.Page = (Form as Form).GetPageById(field.PageId);
                }
                field.Form = Form;
            }

            return fieldCollection;
        }
    }
}
